// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

import React, { useCallback, useContext, useEffect } from 'react';
import { Button, message, Table } from 'antd';
import { useTranslation } from 'react-i18next';
import StatusMark from '@src/components/status-mark';
import { useAsync } from '@src/hooks/use-async';
import * as ClusterAPI from '../cluster.api';
import * as InstanceAPI from '../instance.api';
import { UserInfoContext } from '@src/common/common.context';

import { SpaceAPI } from '../../space/space.api';
import { isSuccess } from '@src/utils/http';

const enum ModuleNameEnum {
    FRONTEND = 'fe',
    BACKEND = 'be',
    BROKER = 'broker',
}

const enum OperateStatusEnum {
    SUCCESS = 'SUCCESS',
    INIT = 'INIT',
    PROCESSING = 'PROCESSING',
    FAIL = 'FAIL',
    CANCEL = 'CANCEL',
}

interface NodeListItem {
    instanceId: number;
    moduleName: ModuleNameEnum;
    nodeHost: string;
    nodeStatus: OperateStatusEnum;
}

export default function Nodes() {
    const { t } = useTranslation();
    const userInfo = useContext(UserInfoContext)!;
    const { data: nodeList, loading, run: runGetNodeList } = useAsync<NodeListItem[]>({ loading: true, data: [] });
    const getNodeListAPiCall = () => {
        runGetNodeList(ClusterAPI.getNodeList(userInfo.space_id), { setStartLoading: false }).catch(res => {
            message.error(res.msg);
        });
    };
    const getNodeListInfo = useCallback(getNodeListAPiCall, [runGetNodeList, userInfo.space_id]);
    useEffect(() => {
        getNodeListInfo();
    }, [getNodeListInfo]);
    const columns = [
        {
            title: t`nodeId`,
            dataIndex: 'instanceId',
        },
        {
            title: t`nodeType`,
            dataIndex: 'moduleName',
            filters: [
                {
                    text: 'Frontend',
                    value: ModuleNameEnum.FRONTEND,
                },
                {
                    text: 'Backend',
                    value: ModuleNameEnum.BACKEND,
                },
                {
                    text: 'Broker',
                    value: ModuleNameEnum.BROKER,
                },
            ],
            onFilter: (value: any, record: NodeListItem) => record.moduleName === value,
            render: (moduleName: ModuleNameEnum) => <span>{resolveModuleName(moduleName)}</span>,
        },
        {
            title: t`hostIp`,
            dataIndex: 'nodeHost',
        },
        {
            title: t`nodeStatus`,
            dataIndex: 'nodeStatus',
            render: (status: OperateStatusEnum) => (
                <StatusMark status={resolveStatusCode(status)}>{resolveStatusName(status)}</StatusMark>
            ),
        },
        {
            title: t`detailsLink`,
            dataIndex: 'detailsLink',
            render: (detailsLink: string) => (
                <a href={detailsLink} target="_blank" rel="noreferrer">
                    {detailsLink}
                </a>
            ),
        },
        {
            title: t`actionButtons`,
            dataIndex: 'instanceId',
            render: (instanceId: string) => (
                <>
                    <Button
                        onClick={() => handleStart(instanceId)}
                        loading={startLoading}
                        disabled={resolveOperateStatus(nodeList, instanceId)}
                        type="primary"
                    >
                        {t`start`}
                    </Button>
                    <Button
                        onClick={() => handleStop(instanceId)}
                        loading={stopLoading}
                        disabled={!resolveOperateStatus(nodeList, instanceId)}
                    >{t`stop`}</Button>
                    <Button
                        onClick={() => handleRestart(instanceId)}
                        loading={restartLoading}
                        disabled={!resolveOperateStatus(nodeList, instanceId)}
                    >{t`restart`}</Button>
                </>
            ),
        },
    ];

    const resolveStatusCode = (status: OperateStatusEnum) => {
        switch (status) {
            case OperateStatusEnum.SUCCESS:
                return 'success';
            case OperateStatusEnum.PROCESSING:
                return 'warning';
            case OperateStatusEnum.FAIL:
                return 'error';
            default:
                return 'error';
        }
    };

    const resolveStatusName = (status: OperateStatusEnum) => {
        switch (status) {
            case OperateStatusEnum.SUCCESS:
                return t`normal`;
            case OperateStatusEnum.PROCESSING:
                return t`processing`;
            case OperateStatusEnum.FAIL:
                return t`abnormal`;
            default:
                return t`abnormal`;
        }
    };

    const resolveModuleName = (moduleName: ModuleNameEnum) => {
        switch (moduleName) {
            case ModuleNameEnum.FRONTEND:
                return 'Frontend';
            case ModuleNameEnum.BACKEND:
                return 'Backend';
            case ModuleNameEnum.BROKER:
                return 'Broker';
            default:
                return '';
        }
    };

    const resolveOperateStatus = (nodeList: NodeListItem[] | undefined, instanceId: string) => {
        if (nodeList) {
            for (const node of nodeList) {
                if (node.instanceId === +instanceId) {
                    return (
                        node.nodeStatus === OperateStatusEnum.SUCCESS ||
                        node.nodeStatus === OperateStatusEnum.PROCESSING
                    );
                }
            }
        }
        return false;
    };

    const { loading: startLoading, run: runClusterStart } = useAsync();
    const { loading: stopLoading, run: runClusterStop } = useAsync();
    const { loading: restartLoading, run: runClusterRestart } = useAsync();

    const handleStart = (instanceId: string) => {
        runClusterStart(InstanceAPI.startInstance(+instanceId))
            .then(() => {
                message.success('启动成功');
                getNodeListInfo();
            })
            .catch(res => message.error(res.msg));
    };

    const handleStop = (instanceId: string) => {
        runClusterStop(InstanceAPI.stopInstance(+instanceId))
            .then(() => {
                message.success('停止成功');
                getNodeListInfo();
            })
            .catch(res => message.error(res.msg));
    };

    const handleRestart = (instanceId: string) => {
        runClusterRestart(InstanceAPI.restartInstance(+instanceId))
            .then(() => {
                message.success('重启成功');
                getNodeListInfo();
            })
            .catch(res => message.error(res.msg));
    };

    return <Table rowKey="instanceId" loading={loading} columns={columns} dataSource={nodeList} />;
}
